package com.test.demo.interceptor;


import com.test.mvcframework.annotations.Component;
import com.test.demo.annotation.Security;
import com.test.mvcframework.interceptor.HandlerInterceptor;
import com.test.mvcframework.pojo.handler.MethodHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author felix
 */
@Component
public class SecurityInterceptor implements HandlerInterceptor {
    Map<String, List<String>> methodPermissions = new ConcurrentHashMap<>();

    @Override
    public boolean intercept(HttpServletRequest request, HttpServletResponse response,
            Object handler) throws IOException {
        MethodHandler methodHandler = (MethodHandler) handler;
        // 从缓存获取方法权限信息
        List<String> permissions =
                getMethodPermissions(methodHandler.getTarget(), methodHandler.getMethod());

        // 根据用户名进行权限校验
        String username = request.getParameter("username");
        for (String permission : permissions) {
            if ("*".equals(permission) || permission.equals(username)) {
                // 无需拦截
                return false;
            }
        }

        // 需要拦截
        response.getWriter().write("MVC: request not enabled: 401!");
        return true;
    }

    private List<String> getMethodPermissions(Object instance, Method method) {
        String key = instance.getClass() + "#" + method.getName();
        List<String> permissions = methodPermissions.get(key);
        if (permissions == null) {
            permissions = new LinkedList<>();

            Security classAnnotation = instance.getClass().getDeclaredAnnotation(Security.class);
            Security methodAnnotation = method.getDeclaredAnnotation(Security.class);
            if (classAnnotation != null || methodAnnotation != null) {
                if (classAnnotation != null) {
                    String[] classPermissions = classAnnotation.value();
                    permissions.addAll(Arrays.asList(classPermissions));
                }
                if (methodAnnotation != null) {
                    String[] methodAnnotations = methodAnnotation.value();
                    permissions.addAll(Arrays.asList(methodAnnotations));
                }
                methodPermissions.put(key, permissions);
            }
        }
        return permissions;
    }
}
